package cn.demoncat.util.lang.entity.data;

/**
 * 数组队列 - 单向
 * 
 * @author 延晓磊
 *
 * @since 2020年6月23日
 */
public class ArrayQueue<E> implements Queue<E> {

	
	// 队列容量/存储器长度
	private final int maxSize;
	// 头部指针：指向队列头（读取时递增，已移除）
	private int front = -1;
	// 尾部指针：指向队列尾（添加时递增，最后插入索引）
	private int rear = -1;
	// 数据存储器
	private final Object[] arr;
	
	/**
	 * 创建队列
	 * 
	 * @param size	容量
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年6月23日
	 */
	public ArrayQueue(int size) {
		super();
		this.maxSize = size;
		this.arr = new Object[maxSize];
	}
	
	/**
	 * 判断队列是否已满
	 * 
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年6月23日
	 */
	public boolean isFull() {
		// 队列已满：因数组超界无法再添加数据
		return rear == maxSize - 1;
	}
	
	/**
	 * 判断队列是否为空
	 * 
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年6月23日
	 */
	@Override
	public boolean isEmpty() {
		// 队列为空：已读取至尾部(没有已添加数据)
		return front == rear;
	}
	
	/**
	 * 添加数据-至队列尾
	 * 
	 * @param o 数据
	 * 
	 * @throws RuntimeException 队列满
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年6月23日
	 */
	@Override
	public void add(E o) {
		if(isFull()) {
			// 队列已满，无法添加
			throw FULL_EX;
		}
		// 递增real
		rear ++;
		// 添加数据到队尾
		arr[rear] = o;
	}
	
	/**
	 * 读取数据-从队列头
	 * 
	 * @return 队头数据
	 * 
	 * @throws RuntimeException 队列为空
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年6月23日
	 */
	@Override
	@SuppressWarnings("unchecked")
	public E get() {
		if (isEmpty()) {
			// 队列为空，无法读取
			throw EMPTY_EX;
		}
		// 递增front
		front ++;
		// 读取队列头部元素
		Object e = arr[front];
        return e == null ? null : (E) e;
	}
	
	/**
	 * 队列长度
	 * 
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年6月23日
	 */
	@Override
	public int size() {
		// 已写 - 已读 = 未读
		return rear - front;
	}
	
	/**
     * 打印
     * 
     * @return
     *
     * @author 延晓磊
     *
     * @since 2020年6月28日
     */
	@Override
	public String toString() {
		// 空队列
		if (isEmpty()) {
			return "[]";
		}
		// 队列头 > 队列尾
		int f = front;
		int r = rear;
		StringBuilder str = new StringBuilder();
		str.append('[');
		while(true) {
			// 读取头部
			f ++;
			str.append(arr[f]);
			// 读取完成
			if (f == r) {
				str.append("]");
				break;
			}else {
				str.append(", ");
			}
		}
        return str.toString();
	}
}
